package wwl.lsf.hellospringboot.test.nio.简单的聊天;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Iterator;
import java.util.Set;

public class ChatServer {

  private Selector selector;

  private ServerSocketChannel serverSocketChannel;

  private static final int PORT = 9999;

  private static final DateTimeFormatter dFormat = DateTimeFormatter
      .ofPattern("yyyy-MM-dd HH:mm:ss");//线程安全


  public ChatServer() {

    try {
      this.selector = Selector.open();

      this.serverSocketChannel = ServerSocketChannel.open();

      serverSocketChannel.bind(new InetSocketAddress(PORT));

      serverSocketChannel.configureBlocking(false);

      serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

      printInfo("服务器已经就绪了");

    } catch (IOException e) {
      e.printStackTrace();
    }
  }


  public void start() throws InterruptedException {

    while (true) {
      try {
        int selectCount = selector.select(2000);
        if (selectCount == 0) {
          continue;
        }

        Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
        while (iterator.hasNext()) {
          SelectionKey key = iterator.next();
          if (key.isAcceptable()) {
            SocketChannel socketChannel = serverSocketChannel.accept();

            socketChannel.configureBlocking(false);

            socketChannel.register(selector, SelectionKey.OP_READ);

            System.out.println(socketChannel.getRemoteAddress().toString() + "上线了");

          }
          if (key.isReadable()) {
            readMsg(key);
          }
          iterator.remove();


        }


      } catch (IOException e) {
        e.printStackTrace();
      }

//      TimeUnit.SECONDS.sleep(1);

    }

  }

  private void readMsg(SelectionKey key) {

    SocketChannel socketChannel = null;

    try {
      socketChannel = (SocketChannel) key.channel();
      ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
      int read = socketChannel.read(byteBuffer);

      if (read > 0) {

        String msg = new String(byteBuffer.array());
        printInfo(msg);
        broadCast(socketChannel, msg);


      }
    } catch (IOException e) {
      try {
        printInfo(socketChannel.getRemoteAddress().toString() + "下线了");
        key.cancel();
        socketChannel.close();
      } catch (IOException ex) {
        ex.printStackTrace();
      }
    }


  }

  private void broadCast(SocketChannel expect, String msg) {
    System.out.println("发送广播开始啦");

    Set<SelectionKey> selectionKeys = selector.keys();

    selectionKeys.forEach(key -> {

      Channel channel = key.channel();
      if (channel instanceof SocketChannel && channel != expect) {

        ByteBuffer wrap = ByteBuffer.wrap(msg.getBytes());
        try {
          ((SocketChannel) channel).write(wrap);
        } catch (IOException e) {
          e.printStackTrace();
        }


      }


    });

  }

  private void printInfo(String msg) {

    System.out.println(dFormat.format(LocalDateTime.now()) + msg);


  }

  public static void main(String[] args) throws InterruptedException {
    ChatServer chatServer = new ChatServer();
    chatServer.start();
  }
}
